package cn.maihe.elg.operation.utils;

import cn.maihe.elg.operation.model.vo.guarantee.TemplateParamsVO;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.google.common.collect.Maps;
import com.lowagie.text.Font;
import com.lowagie.text.pdf.BaseFont;
import fr.opensagres.poi.xwpf.converter.pdf.PdfConverter;
import fr.opensagres.poi.xwpf.converter.pdf.PdfOptions;
import fr.opensagres.xdocreport.itext.extension.font.IFontProvider;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.*;

import java.awt.*;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @Description
 * @Author WJH
 * @Date 2021/05/24
 */
public class DocX2PdfUtil {


    private final static Pattern $ParamRegex = Pattern.compile("(.*)(\\$\\{.+\\})(.*)");

    /**
     * 将word文档， 转换成pdf, 中间替换掉变量
     *
     * @param sourceDocX 源为word文档， 必须为docx文档
     * @param targetPdf  目标输出
     * @param params     需要替换的变量
     * @throws Exception
     */
    public static void docX2Pdf(Path sourceDocX, Path targetPdf, Map<String, String> params) {
        try {
            wordConverterToPdf(Files.newInputStream(sourceDocX), Files.newOutputStream(targetPdf), null, params);
        } catch (Exception e) {
            throw new RuntimeException("docX转换pdf失败:" + e.getMessage(), e);
        }
    }

    public static void docX2Pdf(Path sourceDocX, Path targetPdf) {
        docX2Pdf(sourceDocX, targetPdf, null);
    }

    public static void fmtTemplateDocXByValues(Path templateDocX, Path targetDocX, TemplateParamsVO templateParamsVO) {
        try {
            Configure sPELConfigure = Configure.newBuilder().setElMode(Configure.ELMode.SPEL_MODE).build();
            XWPFTemplate template = XWPFTemplate.compile(Files.newInputStream(templateDocX), sPELConfigure).render(templateParamsVO);
            template.write(Files.newOutputStream(targetDocX));
        } catch (Exception e) {
            throw new RuntimeException("保函模板合成电子保函失败:" + e.getMessage(), e);
        }
    }

    /**
     * 将word文档， 转换成pdf, 中间替换掉变量
     *
     * @param source  源为word文档， 必须为docx文档
     * @param target  目标输出
     * @param params  需要替换的变量
     * @param options PdfOptions.create().fontEncoding( "windows-1250" ) 或者其他
     * @throws Exception
     */
    private static void wordConverterToPdf(InputStream source, OutputStream target, PdfOptions options,
                                           Map<String, String> params) throws Exception {
        XWPFDocument doc = new XWPFDocument(source);
        //${}参数替换
        if (params != null && params.size() != 0) {
            paragraphReplace(doc.getParagraphs(), params);
            for (XWPFTable table : doc.getTables()) {
                for (XWPFTableRow row : table.getRows()) {
                    for (XWPFTableCell cell : row.getTableCells()) {
                        paragraphReplace(cell.getParagraphs(), params);
                    }
                }
            }
        }
        //解决pdf中文
        if (options == null) {
            options = PdfOptions.create();
            options.fontProvider(new MyFontProvider());
        }
        PdfConverter.getInstance().convert(doc, target, options);
    }

    /**
     * 替换段落中内容
     */
    private static void paragraphReplace(List<XWPFParagraph> paragraphs, Map<String, String> params) {
        if (MapUtils.isNotEmpty(params)) {
            for (XWPFParagraph p : paragraphs) {
                for (XWPFRun r : p.getRuns()) {
                    String content = r.getText(r.getTextPosition());
                    //${xxx}格式替换
                    if (StringUtils.isNotEmpty(content) && $ParamRegex.matcher(content).matches()) {
                        r.setText(replaceParam(content, params), 0);
                    }
                }
            }
        }
    }

    private static String replaceParam(String content, Map<String, String> params) {
        String replacedContent = content;
        Iterator<Map.Entry<String, String>> iterator = params.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            replacedContent = replacedContent.replaceAll(String.format("\\$\\{%s\\}", entry.getKey()), entry.getValue());
        }
        return replacedContent;
    }

    static class MyFontProvider implements IFontProvider {
        @Override
        public Font getFont(String familyName, String encoding, float size, int style, Color color) {
            try {
                BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
                Font fontChinese = new Font(bfChinese, 12, style, color);
                if (familyName != null) {
                    fontChinese.setFamily(familyName);
                }
                return fontChinese;
            } catch (Exception e) {
                throw new RuntimeException("MyFontProvider.getFont异常：" + e.getMessage());
            }
        }
    }


    public static void main(String[] args) {
        Path sourcePath = Paths.get("d:/担保保函模板2021.doc");
        Path targetPath = Paths.get("d:/担保保函模板2021.pdf");
        Map<String,String> map = Maps.newHashMap();
        map.put("a", "担保保函模板2021担保保函模板2021担保保函模板2021担保保函模板2021");

        DocX2PdfUtil.docX2Pdf(sourcePath,targetPath,map);

    }
}
